package com.fdb.efp.esb.service.impl.sx;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.fdb.efp.esb.common.constant.ESBTradeNoConstance;
import com.fdb.efp.esb.common.constant.MsLoanConstant;
import com.fdb.basic.framework.core.constant.ESBConstant;
import com.fdb.basic.framework.core.exception.ESBException;
import com.fdb.basic.framework.core.util.SpringContextUtils;
import com.fdb.efp.esb.service.bo.req.hlw.ReqAlarmJudgementBean;
import com.fdb.efp.esb.service.bo.req.sx.YedCreditRiskApproveReq;
import com.fdb.efp.esb.service.bo.resp.hlw.RespAlarmJudgementBean;
import com.fdb.efp.esb.service.bo.resp.sx.YedCreditRiskApproveResp;
import com.fdb.efp.esb.service.client.ESBBeanCreator;
import com.fdb.efp.esb.service.client.impl.YEDESBBeanCreator;
import com.fdb.efp.esb.service.facade.hlw.AlarmJudgementService;
import com.fdb.efp.esb.service.impl.esb.AbstractRetryBaseEsbService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Optional;
import java.util.function.Function;

/**
 * 需求编号：优e贷授信阶段风控审批接口调用<br/>
 * 问题编号：<br/>
 * 功能描述：<br/>
 * 开发人员：dengqiwen<br/>
 * 创建时间：2020/7/28 16:39
 */
@Service("yedCreditRiskApproveService")
public class YedCreditRiskApproveServiceImpl extends AbstractRetryBaseEsbService<YedCreditRiskApproveReq, YedCreditRiskApproveResp> {

    private static Logger logger = LoggerFactory.getLogger(YedCreditRiskApproveServiceImpl.class);

    // 日志ID
    private static final String LOGGER_ID = "优e贷授信阶段风控审批接口";

    @Autowired
    @Qualifier("alarmJudgementService")
    private AlarmJudgementService alarmJudgementService;

    /**
     * 流水号关联
     *
     * @param reqBean
     * @return 流水号
     */
    @Override
    protected String applySeq(YedCreditRiskApproveReq reqBean) {
        if (reqBean.getQryRptsInfArry().size() > 0) {
            return reqBean.getQryRptsInfArry().get(0).getAppNo();
        } else {
            return "";
        }
    }

    /**
     * ESBBeanCreator ，用于配置产品机构号，请求头等信息
     *
     * @return
     */
    @Override
    protected ESBBeanCreator beanFactory() {
        return (YEDESBBeanCreator) SpringContextUtils.getBean("YEDESBBeanCreator");
    }

    /**
     * 对接口返回结果进行处理，并返回包装后的结果
     *
     * @param reqBean
     * @param resBean
     * @return
     * @throws Exception
     */
    @Override
    protected YedCreditRiskApproveResp postProcess(YedCreditRiskApproveReq reqBean, YedCreditRiskApproveResp resBean) throws Exception {
        Optional.
                ofNullable(resBean).
                map(i -> i.getQryRptsInfArry().get(0).getRcvSt()).
                orElseThrow(() -> new ESBException("优e贷授信风控审批接口返回为空！"));
        logger.debug(LOGGER_ID, "优e贷授信风控审批接口进行后续处理，请求参数: " + reqBean + ", 返回结果： " + resBean);
        return resBean;
    }

    /**
     * 各接口的交易码
     *
     * @return
     */
    @Override
    protected String tradeNo() {
        return ESBTradeNoConstance.YED_CREDIT_RISK;
    }

    /**
     * 各接口的服务场景
     *
     * @return
     */
    @Override
    protected String scene() {
        return ESBConstant.SCENE_NO_11;
    }


    /**
     * 执行次数，包括第一次执行
     * 若为3，则第一次执行出错后还会执行2次重试
     *
     * @return
     */
    @Override
    protected Integer retryTimes() {
        return 3;
    }

    /**
     * 等待时间 2分钟
     *
     * @return 单位：毫秒
     */
    @Override
    protected Long waitTime() {
        return 2*60*1000L;
    }

    /**
     * 等待时间跨度
     * 默认为1，若等待时间为5s，跨度为1，则每次间隔的等待时间为5*1=5s, 5*1=5s, 10*1=5s
     * 若等待时间为5s，跨度为2，则每次间隔的等待时间为5*1=5s, 5*2=10s, 10*2=20s
     * 若等待时间为5s，跨度为3，则每次间隔的等待时间为5*1=5s, 5*3=15s, 10*3=30s
     *
     * @return
     */
    @Override
    protected Long timeSpan() {
        return 1L;
    }

    /**
     * 重试失败后执行的操作
     */
    @Override
    protected void retryFailCallback(YedCreditRiskApproveReq reqBean) throws Exception {
        //调用风控失败3次之后，发告警信息
        ReqAlarmJudgementBean reqAlarmJudgementBean = new ReqAlarmJudgementBean();
        reqAlarmJudgementBean.setAlrmInf("优e贷授信阶段风控审批接口调用3次失败！流水号：" + reqBean.getQryRptsInfArry().get(0).getAppNo());
        getrespAlarmJudgementBean(reqAlarmJudgementBean);
        logger.error(LOGGER_ID, "优e贷授信阶段风控审批接口调用重试失败！流水号："+reqBean.getQryRptsInfArry().get(0).getAppNo());
        throw new ESBException("优e贷授信阶段风控审批接口调用3次失败");
    }

    /**
     * 允许自定义成功和失败的判断标准
     *
     * @param res 调用返回值
     * @return
     */
    @Override
    protected boolean isSuccess(YedCreditRiskApproveResp res) {
        return MsLoanConstant.RetCodeEnum.SUCCESS.VALUE.equals(res.getQryRptsInfArry().get(0).getRcvSt());
    }

    @Override
    protected Function<String, YedCreditRiskApproveResp> converter() {
        return i -> JSONObject.parseObject(i, new TypeReference<YedCreditRiskApproveResp>() {
        });
    }

    /**
     *
     * 调用颖风写的告警判断服务
     *
     * @param reqAlarmJudgementBean
     * @return
     * @throws Exception
     * @author liyakui
     * @since 2019年1月28日 上午8:36:25
     * @version 1.0
     */
    public RespAlarmJudgementBean getrespAlarmJudgementBean(ReqAlarmJudgementBean reqAlarmJudgementBean) throws Exception {
        RespAlarmJudgementBean respAlarmJudgementBean = null;
        try {
            // 调用颖风写的告警判断服务
            reqAlarmJudgementBean.setMonObjNm("优e贷");
            reqAlarmJudgementBean.setMonObjSpfTpVal("外部接口");
            reqAlarmJudgementBean.setMonObjLctr(InetAddress.getLocalHost().getHostAddress());// 获取本机IP
            reqAlarmJudgementBean.setAlrmTmstmp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((new Date())));
            reqAlarmJudgementBean.setMonAlrmLvl("3");
            respAlarmJudgementBean = alarmJudgementService.alarmJudgement(reqAlarmJudgementBean);
            logger.debug("调用告警判断返回码：【" + respAlarmJudgementBean.getRetCd() + "】，返回信息：【" + respAlarmJudgementBean.getRetMsg() + "】");
        } catch (Exception e) {
            logger.info("调用告警接口异常！" + e.getMessage());
            throw e;
        }
        return respAlarmJudgementBean;
    }
}
